using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Core;
using Core.ListViewObjectModel;
using System.Xml;
using Microsoft.SharePoint.WebControls;
using System.Xml.Xsl;
using System.Globalization;
using System.IO;
using System.Reflection;

namespace FlexListViewerMOSS
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:FlexListViewer runat=server></{0}:FlexListViewer>")]
    public class FlexListViewer : WebPart
    {
        #region Public properties
        private string _listUrl = string.Empty;
        [Browsable(true),
        Category("Options"),
        DefaultValue(""),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),       
        WebDisplayName("List View Url"),
        Description("Url of a view of the list")]
        public string ListUrl
        {
            get
            {
                return _listUrl;
            }
            set
            {
                _listUrl = value.Trim();

                if (_listUrl.Length > 0)
                {
                    // Escape spaces (don't just url-escape, since it may have been escaped already)
                    _listUrl = _listUrl.Replace(" ", "%20");
                    // Was the url of the list itself instead of the view specified: default to AllItems.aspx.
                    if (!_listUrl.ToLower().EndsWith(".aspx"))
                    {
                        if (!_listUrl.EndsWith("/"))
                            _listUrl += "/";
                        _listUrl += "AllItems.aspx";
                    }
                }
            }
        }

        private string _xsltUrl = string.Empty;
        [Browsable(true),
        Category("Options"),
        DefaultValue(""),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("Xslt Url"),
        Description("Url to the Xslt-file which renders the HTML.")]
        public string XsltUrl
        {
            get
            {
                return _xsltUrl;
            }
            set
            {
                _xsltUrl = value;
            }
        }

        private const string DEFAULT_MSG_ADDNEWITEM = "Add a new item";
        private string _msgAddNewItem = DEFAULT_MSG_ADDNEWITEM;
        [Browsable(true),
        Category("Messages"),
        DefaultValue(DEFAULT_MSG_ADDNEWITEM),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("Message"),
        Description("Title of the 'add new item'-link.")]
        public string MsgAddNewItem
        {
            get
            {
                return _msgAddNewItem;
            }
            set
            {
                _msgAddNewItem = value;
            }
        }

        private const string DEFAULT_MSG_YES = "Yes";
        private string _msgYes = DEFAULT_MSG_YES;
        [Browsable(true),
        Category("Messages"),
        DefaultValue(DEFAULT_MSG_YES),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("'Yes'-message"),
        Description("Text to be displayed for the boolean value 'True'")]
        public string MsgYes
        {
            get
            {
                return _msgYes;
            }
            set
            {
                _msgYes = value;
            }
        }

        private const string DEFAULT_MSG_NO = "No";
        private string _msgNo = DEFAULT_MSG_NO;
        [Browsable(true),
        Category("Messages"),
        DefaultValue(DEFAULT_MSG_NO),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("'No'-message"),
        Description("Text to be displayed for the boolean value 'False'")]
        public string MsgNo
        {
            get
            {
                return _msgNo;
            }
            set
            {
                _msgNo = value;
            }
        }

        private const bool DEFAULT_ALLOWADDNEWITEM = true;
        private bool _allowAddNewItem = DEFAULT_ALLOWADDNEWITEM;
        [Browsable(true),
        Category("Options"),
        DefaultValue(DEFAULT_ALLOWADDNEWITEM),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("'Add new item' enabled"),
        Description("Specifies whether the 'Add new item'-link is displayed.")]
        public bool AllowAddNewItem
        {
            get
            {
                return _allowAddNewItem;
            }
            set
            {
                _allowAddNewItem = value;
            }
        }

        private const bool DEFAULT_DISPLAYXML = false;
        private bool _displayXML = DEFAULT_DISPLAYXML;
        [Browsable(true),
        Category("Options"),
        DefaultValue(DEFAULT_DISPLAYXML),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("Display XML (for debugging purposes)"),
        Description("Specifies whether the composed XML must be displayed.")]
        public bool DisplayXML
        {
            get
            {
                return _displayXML;
            }
            set
            {
                _displayXML = value;
            }
        }

        #region Parameter-properties
        private string[] _params = new string[5];
        [Browsable(true),
        Category("Parameters"),
        DefaultValue(""),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("Parameter 1"),
        Description("Parameter to send to xslt.")]
        public string Param1
        {
            get
            {
                return _params[0];
            }
            set
            {
                _params[0] = value;
            }
        }
        [Browsable(true),
        Category("Parameters"),
        DefaultValue(""),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("Parameter 2"),
        Description("Parameter to send to xslt.")]
        public string Param2
        {
            get
            {
                return _params[1];
            }
            set
            {
                _params[1] = value;
            }
        }
        [Browsable(true),
        Category("Parameters"),
        DefaultValue(""),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("Parameter 3"),
        Description("Parameter to send to xslt.")]
        public string Param3
        {
            get
            {
                return _params[2];
            }
            set
            {
                _params[2] = value;
            }
        }
        [Browsable(true),
        Category("Parameters"),
        DefaultValue(""),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),            
        WebDisplayName("Parameter 4"),
        Description("Parameter to send to xslt.")]
        public string Param4
        {
            get
            {
                return _params[3];
            }
            set
            {
                _params[3] = value;
            }
        }
        [Browsable(true),
        Category("Parameters"),
        DefaultValue(""),
        WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),        
        WebDisplayName("Parameter 5"),
        Description("Parameter to send to xslt.")]
        public string Param5
        {
            get
            {
                return _params[4];
            }
            set
            {
                _params[4] = value;
            }
        }
        #endregion
        #endregion

        protected override void RenderContents(HtmlTextWriter output)
        {
            if (ListUrl.Trim().Equals(string.Empty))
            {
                output.Write("Please configure the URL for the list to be displayed.");
                return;
            }

            SPView view;

            try
            {
                // Get reference to the SPView
                view = SPListUtil.GetViewForUrl(ListUrl, Context);
                if (view == null)
                    throw (new ArgumentException("Non-existing list or view specified.", "List Url"));
            }
            catch (Exception ex)
            {
                output.WriteLine("Cannot access the view of the list. Are you authorized?<br/>");
                output.WriteLine("Details: " + ex.Message);
                return;
            }

            try
            {
                // Generate an objectmodel from the view
                Core.ListViewObjectModel.ListView listView = SPListUtil.GenerateListViewObjectModel(view);

                // Serialize the objectmodel to XML
                XmlDocument docListXml = XMLUtil.SerializeObjectModel(listView, typeof(Core.ListViewObjectModel.ListView));

                if (_displayXML)
                {
                    output.WriteLine(Page.Server.HtmlEncode(docListXml.InnerXml) + "<br/>");
                }

                // Load the XSLT to transform the XML to HTML
                XmlDocument docListXsl = new XmlDocument();
                try
                {
                    if (_xsltUrl.Length > 0)
                    {
                        docListXsl.LoadXml(FileUtil.LoadDocument(_xsltUrl, Context));
                    }
                    else
                    {
                        Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(this.GetType(), "StandardList.xslt");
                        docListXsl.Load(s);
                    }

                }
                catch (Exception ex)
                {
                    output.WriteLine("Cannot read the specified Xslt-file.<br/>");
                    output.WriteLine("Details: " + ex.Message);
                    return;
                }

                // DEBUG
                //output.Write("Xslt:[" + ((_xsltUrl.Length > 0) ? _xsltUrl : ClassResourcePath + "/" + "StandardList.xslt") + "]");

                // Perform the transformation
                SPWeb web = SPControl.GetContextWeb(Context);
                XsltArgumentList args = new XsltArgumentList();
                args.AddParam("currentPage", "", Page.Request.Url.AbsoluteUri);
                args.AddParam("currentSiteUrl", "", web.Url + "/");
                args.AddParam("lcid", "", web.Language.ToString());
                args.AddParam("allowAddNewItem", "", _allowAddNewItem.ToString());
                args.AddParam("msgAddNewItem", "", _msgAddNewItem);
                args.AddParam("msgYes", "", (_msgYes.Length > 0) ? _msgYes : Microsoft.SharePoint.Strings.Yes);
                args.AddParam("msgNo", "", (_msgNo.Length > 0) ? _msgNo : Microsoft.SharePoint.Strings.No);
                for (int paramCount = 0; paramCount < _params.Length; paramCount++)
                {
                    string paramValue = (_params[paramCount] != null) ? _params[paramCount] : string.Empty;
                    args.AddParam("param" + (paramCount + 1).ToString(CultureInfo.InvariantCulture), "", paramValue);
                }

                string html = XMLUtil.TransformXml(docListXml, docListXsl, args, this.GetType().Assembly.Evidence);

                // Write the HTML to the output
                output.Write(html);
            }
            catch (Exception ex)
            {
                // Display the exception
                output.WriteLine("Error occurred: " + ex.Message + "<br/>");
                output.WriteLine("Details: " + ex.ToString() + "<br/>" + ex.StackTrace);
            }

            base.RenderContents(output);
        }
    }
}
